/*
 * Copyright (C) 2015  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


/**
 * @file
 * @brief Functions to detect collisions of 2D elements with unsigned members.
 */


#ifndef PLANET_WARS_2D_RT_CORE_COLLISION_2D_UINT_H
#define PLANET_WARS_2D_RT_CORE_COLLISION_2D_UINT_H


#include "PlanetWars2dRT-core/utils/collision_2d_generic.h"
#include "PlanetWars2dRT-core/utils/position_2d_uint.h"
#include "PlanetWars2dRT-core/utils/size_2d_uint.h"
#include <stdlib.h>


EXTERN_C_BEGIN


static inline
bool
collision_2d_line_line_uint(const position_2d_uint* line1_start,
			    const position_2d_uint* line2_start,
			    const position_2d_uint* line1_end,
			    const position_2d_uint* line2_end)
{
  return COLLISION_2D_LINE_LINE_STRUCT(line1_start, line2_start,
				       line1_end,   line2_end);
}

static inline
bool
collision_2d_rectangle_rectangle_uint(const position_2d_uint* pos1,
				      const position_2d_uint* pos2,
				      const size_2d_uint* size1,
				      const size_2d_uint* size2)
{
  return COLLISION_2D_RECTANGLE_RECTANGLE_STRUCT(pos1, pos2, size1, size2);
}

static inline
bool
collision_2d_circle_circle_uint(const position_2d_uint* pos1,
				const position_2d_uint* pos2,
				const unsigned int radius1,
				const unsigned int radius2)
{
  int dx = ((int) pos1->x) - ((int) pos2->x);
  int dy = ((int) pos1->y) - ((int) pos2->y);
  unsigned int squaredistance = (unsigned int) dx * dx + dy * dy;
  return squaredistance <= (radius1 + radius2) * (radius1 + radius2);
}

static inline
bool
collision_2d_circle_rectangle_uint(const position_2d_uint* rect_pos_top_left,
				   const size_2d_uint*     rect_size,
				   const position_2d_uint* circle_pos_center,
				   const unsigned int      circle_radius)
{
  /* circle_dist for x and y */
  unsigned int tmp_x =
    (unsigned int) abs(((int) circle_pos_center->x) - ((int) rect_pos_top_left->x));
  unsigned int tmp_y =
    (unsigned int) abs(((int) circle_pos_center->y) - ((int) rect_pos_top_left->y));
  
  /* circle is far enough away from the rectangle */
  if(tmp_x > rect_size->x / 2 + circle_radius ||
     tmp_y > rect_size->y / 2 + circle_radius)
    {
      return false;
    }
  
  /* circle is close enough to the rectangle */
  if(tmp_x <= rect_size->x / 2 ||
     tmp_y <= rect_size->y / 2)
    {
      return true;
    }
  
  tmp_x = tmp_x - rect_size->x / 2;
  tmp_y = tmp_y - rect_size->y / 2;
  const unsigned int corner_distance_pow2 =
    tmp_x * tmp_x +
    tmp_y * tmp_y;
  
  return corner_distance_pow2 <= circle_radius * circle_radius;
}


static inline
bool
is_size_in_size_2d_uint(const size_2d_uint* size1,
			const size_2d_uint* size2)
{
  return IS_SIZE_IN_SIZE_2D_STRUCT(size1, size2);
}

static inline
bool
is_rectangle_in_size_2d_uint(const size_2d_uint*     size1,
			     const position_2d_uint* pos2,
			     const size_2d_uint*     size2)
{
  return IS_RECTANGLE_IN_SIZE_2D_STRUCT(size1, pos2, size2);
}

static inline
bool
is_rectangle_in_rectangle_2d_uint(const position_2d_uint* pos1,
				  const position_2d_uint* pos2,
				  const size_2d_uint* size1,
				  const size_2d_uint* size2)
{
  return IS_RECTANGLE_IN_RECTANGLE_2D_STRUCT(pos1, pos2, size1, size2);
}


EXTERN_C_END


#endif
